高阶函数
接受函数为参数,或者把函数作为结果返回的函数是高阶函数
def reverse(word):
return word[::-1]
fruits = ['strawberry', 'fig', 'apple', 'cherry', 'raspberry', 'banana']
print(reverse('testing'))
print(sorted(fruits, key=reverse))
all 和 any 也是内置的归约函数。
all(iterable)
如果 iterable 的每个元素都是真值,返回 True;all([]) 返回True。
any(iterable)
只要 iterable 中有元素是真值,就返回 True;any([]) 返回False。
匿名函数
fruits = ['strawberry', 'fig', 'apple', 'cherry', 'raspberry', 'banana']
print(sorted(fruits, key=lambda word: word[::-1]))
可调用对象
如果类定义了 call 方法,那么它的 实例 可以作为函数调用。
因此判断对象能否调用,最安全的方法是使用内置的 callable() 函数
实现 call 方法的类是创建函数类对象的简便方式,
函数内省
用户定义的函数的属性 page 252
案例 生成html标签的函数
def tag(name, *content, cls=None, **attrs):
"""生成一个或多个HTML标签"""
if cls is not None:
attrs['class'] = cls
if attrs:
attr_str = ''.join(' %s="%s"' % (attr, value)
for attr, value
in sorted(attrs.items()))
else:
attr_str = ''
if content:
return '\n'.join('<%s%s>%s</%s>' % (name, attr_str, c, name) for c in content)
else:
return '<%s%s />' % (name, attr_str)
print(tag('br'))
print(tag('p', 'hello'))
print(tag('p', 'hello', 'world'))
print(tag('p', 'hello', 'world', cls='sidebar'))
获取关于参数的信息
import bobo
@bobo.query('/')
def hello(person):
return 'Hello %s!' % person
bobo.query 装饰器把一个普通的函数(如 hello)与框架的请求处理
机制集成起来了。
Bobo 会内省 hello 函数,发现它需要一个名为 person
的参数,然后从请求中获取那个名称对应的参数,将其传给 hello 函
数,因此程序员根本不用触碰请求对象。
提取关于函数参数的信息
使用 inspect 模块
from clip import clip
from inspect import signature
sig = signature(clip)
print(sig)
print(str(sig))
for name, param in sig.parameters.items():
print(param.kind, ':', name, '=', param.default)
inspect.signature 函数返回一个inspect.Signature 对象
- 它有一个 parameters 属性,这是一个有序映射,
- 把参数名和 inspect.Parameter 对象对应起来。
- 各个Parameter 属性也有自己的属性,
- 例如 name、default 和 kind。特殊的 inspect._empty 值表示没有默认值
kind 属性的值是 _ParameterKind 类中的 5 个值之一,列举如下。
-
POSITIONAL_OR_KEYWORD
可以通过定位参数和关键字参数传入的形参(多数 Python 函数的参数属于此类)。
-
VAR_POSITIONAL
定位参数元组。
-
VAR_KEYWORD
关键字参数字典。
-
KEYWORD_ONLY
仅限关键字参数(Python 3 新增)。
-
POSITIONAL_ONLY
仅限定位参数;
inspect.Signature 对象有个 bind 方法,
它可以把任意个参数绑定到签名中的形参上,所用的规则与实参到形参的匹配方式一样。
框架可以使用这个方法在真正调用函数前验证参数,
示例 5-18 把tag 函数(见示例 5-10)的签名绑定到一个参数字典
上
>>> import inspect
>>> sig = inspect.signature(tag) ➊
>>> my_tag = {'name': 'img', 'title': 'Sunset Boulevard',
... 'src': 'sunset.jpg', 'cls': 'framed'}
>>> bound_args = sig.bind(**my_tag) ➋
>>> bound_args
<inspect.BoundArguments object at 0x...> ➌
>>> for name, value in bound_args.arguments.items(): ➍
... print(name, '=', value)
...
name = img
cls = framed
attrs = {'title': 'Sunset Boulevard', 'src': 'sunset.jpg'}
>>> del my_tag['name'] ➎
>>> bound_args = sig.bind(**my_tag) ➏
Traceback (most recent call last):
...
TypeError: 'name' parameter lacking default value
❷ 把一个字典参数传给 .bind() 方法。
❸ 得到一个 inspect.BoundArguments 对象。
❹ 迭代 bound_args.arguments(一个 OrderedDict 对象)中的元
素,显示参数的名称和值。
❺ 把必须指定的参数 name 从 my_tag 中删除。
❻ 调用 sig.bind(**my_tag),抛出 TypeError,抱怨缺少 name 参
数。
函数注解
def clip(text: str, max_len: 'int > 0' = 80) -> str:
print(text, max_len)
clip("sdf", 18)
print(clip.__annotations__)
- 如果想注解返回值,在 ) 和函数声明末尾的 : 之间添加 -> 和一个表达式。
- 各个参数可以在 : 之后增加注解表达式。如果参数有默认值,注解放在参数名和 = 号之间。
注解不会做任何处理,只是存储在函数的 annotations 属性(一
个字典)中:
operator模块
reduce计算阶乘
from functools import reduce
# 阶乘
def fact(n):
print(reduce(lambda a, b: a * b, range(1, n + 1)))
# operator.mul 函数计算阶乘
from functools import reduce
from operator import mul
def fact2(n):
return reduce(mul, range(1, n + 1))
print(fact2(3))
itemgetter
展示了 itemgetter 的常见用途:根据元组的某个字段给元
组列表排序。在这个示例中,按照国家代码(第 2 个字段)的顺序打印
各个城市的信息。
metro_data = [
('Tokyo', 'JP', 36.933, (35.689722, 139.691667)),
('Delhi NCR', 'IN', 21.935, (28.613889, 77.208889)),
('Mexico City', 'MX', 20.142, (19.433333, -99.133333)),
('New York-Newark', 'US', 20.104, (40.808611, -74.020386)),
('Sao Paulo', 'BR', 19.649, (-23.547778, -46.635833)),
]
### 演示使用 itemgetter 排序一个元组列表
from operator import itemgetter
for city in sorted(metro_data, key=itemgetter(1)):
print(city)
如果把多个参数传给 itemgetter,它构建的函数会返回提取的值构成
的元组:
cc_name = itemgetter(1, 0)
for city in metro_data:
print(cc_name(city))
attrgetter
此外,如果参数名中包含 .(点号),attrgetter 会深
入嵌套对象,获取指定的属性。
from collections import namedtuple
metro_data = [
('Tokyo', 'JP', 36.933, (35.689722, 139.691667)),
('Delhi NCR', 'IN', 21.935, (28.613889, 77.208889)),
('Mexico City', 'MX', 20.142, (19.433333, -99.133333)),
('New York-Newark', 'US', 20.104, (40.808611, -74.020386)),
('Sao Paulo', 'BR', 19.649, (-23.547778, -46.635833)),
]
## 就像数据格式化一样 数据带上标签
LatLong = namedtuple('LatLong', 'lat long')
Metropolis = namedtuple('Metropolis', 'name cc pop coord')
metro_areas = [Metropolis(name, cc, pop, LatLong(lat, long))
for name, cc, pop, (lat, long) in metro_data]
print(metro_areas[0])
print(metro_areas[0].coord.lat)
#
from operator import attrgetter
name_lat = attrgetter('name', 'coord.lat')
for city in sorted(metro_areas, key=attrgetter('coord.lat')):
print(name_lat(city))
methodcaller 自行创建函数
它会自行创建函数。methodcaller 创建的函数会在对象上调用参数指定的方法
自己创建函数
from operator import methodcaller
s = 'The time has come'
upcase = methodcaller('upper')
print(upcase)
hiphenate = methodcaller('replace', ' ', '-')
print(hiphenate(s))
functools.partial冻结参数
functools.partial 这个高阶函数用于部分应用一个函数。部分应用
是指,基于一个函数创建一个新的可调用对象,把原函数的某些参数固定。
from operator import mul
from functools import partial
print(mul(3, 7))
# 第一个函数, 第二个固定的参数
triple = partial(mul, 3)
print(list(map(triple, range(1, 10))))
小总结
高阶函数
- 接受函数为参数,或者把函数作为结果返回的函数是高阶函数.
- Python 中常用的高阶函数有内置函数
- sorted、min、max 和 functools. partial
实例 直接函数化运行
- 从 lambda 表达式创建的简单函数到实现__call__ 方法的类实例。
- 这些可调用对象都能通过内置的callable() 函数检测。
函数注解
- 在 inspect 模块的帮助下,可以读取它们。
- 例如,Signature.bind 方法使用灵活的规则把实参绑定到形参上,这与 Python 使用的规则一样。
operator 模块
- 介绍了 operator 模块中的一些函数,
- 以及functools.partial 函数,
- 有了这些函数,函数式编程就不太需要功能有限的 lambda 表达式了
其他
- all 和 any 也是内置的归约函数.
- 用来判断是否所有都为真,或者有一个为真
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。